﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Collections.ObjectModel;
using ShredTheLog.Api.DataContracts.TextChat;
using ShredTheLog.Api.DataContracts;
using ShredTheLog.Api;

namespace ShredTheLog.Model
{
    public interface IShredRequest
    {
    }

    [XmlRoot("S")]
    public sealed class UserSearchRequest : IShredRequest
    {
        [XmlAttribute("C")]
        public int RowCount { get { return 100; } }

        [XmlIgnore]
        public Language? KnownLanguage { get; private set; }

        [XmlAttribute("KL")]
        public int? KnownLanguageId { get { return KnownLanguage.HasValue ? (int?)KnownLanguage.Value : null; } }

        [XmlIgnore]
        public Language? PracticingLanguage { get; private set; }

        [XmlAttribute("PL")]
        public int? PracticingLanguageId { get { return PracticingLanguage.HasValue ? (int?)PracticingLanguage.Value : null; } }

        [XmlIgnore]
        public bool? ChatsOnline { get; private set; }

        [XmlAttribute("XCC")]
        public int? DoesNotChatOnline { get { return ChatsOnline.HasValue ? (int?)(ChatsOnline.Value ? 0 : 1) : null; } }

        [XmlIgnore]
        public Country? Country { get; private set; }

        [XmlAttribute("LID")]
        public int? CountryId { get { return Country.HasValue ? (int?)Country.Value : null; } }

        [XmlAttribute("BA")]
        public int? MinAge { get; private set; }

        [XmlAttribute("TA")]
        public int? MaxAge { get; private set; }

        [XmlAttribute("FN")]
        public string FirstName { get; private set; }

        [XmlAttribute("LN")]
        public string LastName { get; private set; }

        [XmlAttribute("PRL")]
        public string Location { get; private set; }

        [XmlIgnore]
        public IUserInfo LastViewedUser { get; private set; }

        [XmlAttribute("BUID")]
        public int? LastViewedUserUid { get { return LastViewedUser != null ? (int?)LastViewedUser.Uid : null; } }

        public UserSearchRequest(Language? knownLanguage, Language? practicingLanguage, bool? chatsOnline, Country? country, int? minAge, int? maxAge, string firstName, string lastName, string location, IUserInfo lastViewedUser)
        {
            KnownLanguage = knownLanguage;
            PracticingLanguage = practicingLanguage;
            ChatsOnline = chatsOnline;
            Country = country;
            MinAge = minAge;
            MaxAge = maxAge;
            FirstName = firstName;
            LastName = lastName;
            Location = location;
            LastViewedUser = lastViewedUser;
        }
    }

    [XmlRoot("LangPackRequests")]
    public sealed class GetLanguagePacksRequest : ReadOnlyCollection<GetLanguagePacksRequest.LanguagePackRequest>, IShredRequest
    {
        public GetLanguagePacksRequest(GetLanguagePacksRequest.LanguagePackRequest[] packRequests)
            : base(packRequests)
        {
            Contract.Requires(packRequests != null);
        }

        [XmlRoot("LangPack")]
        public sealed class LanguagePackRequest
        {
            public LanguagePackRequest(string language, string group)
            {
                Contract.Requires(!String.IsNullOrWhiteSpace(language));
                Contract.Requires(!String.IsNullOrWhiteSpace(group));

                Language = language;
                Group = group;
            }

            [XmlAttribute("L")]
            public string Language { get; private set; }

            [XmlAttribute("G")]
            public string Group { get; private set; }
        }
    }

    [XmlRoot("LI")]
    public sealed class LogInRequest : IShredRequest
    {
        public LogInRequest(string userName, string password)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(userName));
            Contract.Requires(!String.IsNullOrEmpty(password));

            UserName = userName;
            Password = password;
        }

        [XmlAttribute("PW")]
        public string Password { get; private set; }

        [XmlAttribute("UN")]
        public string UserName { get; private set; }
    }

    [XmlRoot("U")]
    public sealed class GetFullUserInfoRequest : IShredRequest
    {
        [XmlAttribute("UID")]
        public int Uid { get; private set; }

        public GetFullUserInfoRequest(IUserInfo user)
        {
            Contract.Requires(user != null);

            Uid = user.Uid;
        }
    }

    [XmlRoot("UPDs")]
    public sealed class GetTextChatUpdatesRequest : ReadOnlyCollection<ITextChatCommand>, IShredRequest
    {
        public GetTextChatUpdatesRequest(int lastUpdateDuration, int uid, Guid sessionId, int lastInUpdateId, int updatesCount, IEnumerable<string> rooms, ITextChatCommand[] commands)
            : base(commands)
        {
            Contract.Requires(rooms != null);
            Contract.Requires(commands != null);

            LastUpdateDuration = lastUpdateDuration;
            Uid = uid;
            SessionId = sessionId;
            LastInUpdateId = lastInUpdateId;
            UpdatesCount = updatesCount;
            Rooms = String.Join(",", rooms);
        }

        [XmlAttribute("D")]
        public int LastUpdateDuration { get; private set; }

        [XmlAttribute("UID")]
        public int Uid { get; private set; }

        [XmlAttribute("GUID")]
        public Guid SessionId { get;  private set; }

        [XmlAttribute("LUPD")]
        public int LastInUpdateId { get; private set; }

        [XmlAttribute("UPDC")]
        public int UpdatesCount { get; private set; }

        [XmlAttribute("Rs")]
        public string Rooms { get; private set; }
    }

    [XmlRoot("U")]
    public sealed class JoinTextChatRequest : ShortUserInfo, IShredRequest
    {
        public JoinTextChatRequest(ISessionCredentials user)
        {
            Contract.Requires(user != null);

            Uid = user.Uid;
            FirstName = user.FirstName;
            LastName = user.LastName;
            Gender = user.Gender;
            Age = user.Age;
            Country = user.Country;
            KnownLanguages = user.KnownLanguages;
            PracticingLanguages = user.PracticingLanguages;
            Ssid = user.Ssid;
        }
    
        [XmlAttribute("SSID")]
        public string Ssid { get; set; }
    }

    [XmlRoot("G")]
    public sealed class JoinTextChatAnonymouslyRequest : IShredRequest
    {
    }

    [XmlRoot("U")]
    public sealed class GetContactListRequest : IShredRequest
    {
        [XmlAttribute("SSID")]
        public string Ssid { get; private set; }

        [XmlAttribute("UID")]
        public int Uid { get; private set; }

        public GetContactListRequest(ISessionCredentials user)
        {
            Contract.Requires(user != null);

            Uid = user.Uid;
            Ssid = user.Ssid;
        }
    }

    [XmlRoot("U")]
    public sealed class AddContactRequest : IShredRequest
    {
        [XmlAttribute("SRC")]
        public string Source { get { return "SubTextChat"; } }

        [XmlAttribute("CID")]
        public int ContactUid { get; private set; }

        [XmlAttribute("SSID")]
        public string Ssid { get; private set; }

        [XmlAttribute("UID")]
        public int Uid { get; private set; }

        public AddContactRequest(ISessionCredentials user, IUserInfo contact)
        {
            Contract.Requires(user != null);
            Contract.Requires(contact != null);

            Uid = user.Uid;
            Ssid = user.Ssid;
            ContactUid = contact.Uid;
        }
    }

    [XmlRoot("U")]
    public sealed class DeleteContactRequest : IShredRequest
    {
        [XmlAttribute("CID")]
        public int ContactUid { get; private set; }

        [XmlAttribute("SSID")]
        public string Ssid { get; private set; }

        [XmlAttribute("UID")]
        public int Uid { get; private set; }

        public DeleteContactRequest(ISessionCredentials user, IUserInfo contact)
        {
            Contract.Requires(user != null);
            Contract.Requires(contact != null);

            Uid = user.Uid;
            Ssid = user.Ssid;
            ContactUid = contact.Uid;
        }
    }
}
